package com.zcyh.exam.job.scheduling;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zcyh.exam.mapper.ScheduledMapper;
import com.zcyh.exam.model.entity.SpringScheduledCron;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * 启动调度器，只能启动一个
 * @author timo 2021/4/1
 */
//@Configuration
@EnableScheduling
public class ScheduledConfig implements SchedulingConfigurer {
    @Autowired
    private ApplicationContext context;
    @Autowired
    private ScheduledMapper scheduledMapper;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        List<SpringScheduledCron> springScheduledCrons = scheduledMapper.selectList(Wrappers.<SpringScheduledCron>lambdaQuery()
                .eq(SpringScheduledCron::getStatus,1)
        );
        for (SpringScheduledCron springScheduledCron : springScheduledCrons) {
            Class<?> clazz;
            Object task;
            try {
                clazz = Class.forName(springScheduledCron.getCronKey());
                task = context.getBean(clazz);
            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException("spring_scheduled_cron表数据" + springScheduledCron.getCronKey() + "有误", e);
            } catch (BeansException e) {
                throw new IllegalArgumentException(springScheduledCron.getCronKey() + "未纳入到spring管理", e);
            }
            Assert.isAssignable(ScheduledOfTask.class, task.getClass(), "定时任务类必须实现ScheduledOfTask接口");
            // 可以通过改变数据库数据进而实现动态改变执行周期
            taskRegistrar.addTriggerTask(((Runnable) task),
                    triggerContext -> {
                        return new CronTrigger(springScheduledCron.getCronExpression()).nextExecutionTime(triggerContext);
                    }
            );
        }
    }
    @Bean
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(10);
    }
}
